package com.alibaba.algo.apiimpl.feign;

import com.alibaba.algo.cooperation.common.BaseResult;
import com.alibaba.algo.cooperation.feign.service.ResourceFeignService;
import com.alibaba.algo.cooperation.feign.vo.enums.OperateEnum;
import com.alibaba.algo.cooperation.feign.vo.req.*;
import com.alibaba.algo.cooperation.feign.vo.res.*;
import com.alibaba.algo.core.exception.BaseException;
import com.alibaba.algo.domain.user.SysResourceDomain;
import com.alibaba.algo.domain.user.SysUserRoleDomain;
import com.alibaba.algo.entity.user.SysResource;
import com.alibaba.algo.entity.user.SysResourceAction;
import com.alibaba.algo.exception.BaseErrorCode;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author fan.tianpeng
 * @date 2021/5/13 10:02
 */
//不兼容现有资源模型，暂时弃用待改
@RestController
public class ResourceFeignServiceImpl implements ResourceFeignService {

    @Autowired
    private SysResourceDomain sysResourceDomain;

    @Autowired
    SysUserRoleDomain sysUserRoleDomain;

    //查询用户所拥有的资源(菜单和按钮)列表


    @Override
    public BaseResult<List<ResourceResVO>> qryResourceListByUserIdForSub(@RequestParam(value = "userId") Long userId,
                                                                         @RequestParam(value = "appCode") String appCode) {
        SelectRoleResourceReqVO paramVO = getSelectRoleResourceReqVO(userId, appCode, null);
        if (CollectionUtils.isEmpty(paramVO.getRoleIdList())) {
            return BaseResult.buildSuccess(new ArrayList<>());
        }
        List<ResourceResVO> menuList = sysResourceDomain.qryResourceListByRoleId(paramVO);
        menuList.forEach(item -> {
            if (item.getHasChild()) {
                item.setChildrenResource(qryChildResource(appCode, paramVO.getRoleIdList(), item.getResourceId()));
            }
        });
        return BaseResult.buildSuccess(menuList);
    }

    private SelectRoleResourceReqVO getSelectRoleResourceReqVO(Long userId, String appCode, String resourceCode) {
        List<UserRoleInfoResVO> userRoleInfo = sysUserRoleDomain.selectRoleListByUserId(userId, appCode, null);
        List<Long> roleIds = userRoleInfo.stream().map(UserRoleInfoResVO::getRoleId).collect(Collectors.toList());
        SelectRoleResourceReqVO paramVO = new SelectRoleResourceReqVO();
        paramVO.setRoleIdList(roleIds);
        //课题专属--提供给mom课题基础底座
        paramVO.setMenuFlag(3);
        paramVO.setAppCode(appCode);
        if (!StringUtils.isEmpty(resourceCode)) {
            paramVO.setResourceCode(resourceCode);
        }
        return paramVO;
    }

    @Override
    public BaseResult<ResourceResVO> qryResourceAndActionByUserIdForSub(@RequestParam(value = "userId") Long userId,
                                                                        @RequestParam(value = "appCode") String appCode,
                                                                        @RequestParam(value = "systemCode") String systemCode) {
        List<UserRoleInfoResVO> userRoleInfo = sysUserRoleDomain.selectRoleListByUserId(userId, appCode, null);
        List<Long> roleIds = userRoleInfo.stream().map(UserRoleInfoResVO::getRoleId).collect(Collectors.toList());

        SysResource sysResource = sysResourceDomain.qryResourceByResourceCodeAndAppCode(systemCode, appCode);
        if (ObjectUtils.isEmpty(sysResource) || !sysResource.getMenuFlag().equals(3)) {
            return BaseResult.buildSuccess(new ArrayList<>());
        }
        //当前系统下的菜单
        ResourceResVO menuTree = new ResourceResVO();
        BeanUtils.copyProperties(sysResource, menuTree);
        List<ResourceResVO> menuList = sysResourceDomain.getChildResourceListByParentIdForSub(appCode, roleIds, sysResource.getId());
        menuList.forEach(item -> {
            if (item.getHasChild()) {
                item.setChildrenResource(qryChildResource(appCode, roleIds, item.getResourceId()));
            }
            item.setAction(getResourceActionList(item.getResourceId(), appCode));
        });
        menuTree.setChildrenResource(menuList);
        return BaseResult.buildSuccess(menuTree);
    }

    private List<ResourceResVO> qryChildResource(String appCode, List<Long> roleIds, Long parentId) {
        List<ResourceResVO> resources = sysResourceDomain.getChildResourceListByParentIdForSub(appCode, roleIds, parentId);
        resources.forEach(item -> {
            if (item.getHasChild()) {
                item.setChildrenResource(qryChildResource(appCode, roleIds, item.getResourceId()));
            }
            item.setAction(getResourceActionListByRole(item.getResourceId(), appCode, roleIds));
        });
        return resources;
    }

    private List<ActionResVO> getResourceActionListByRole(Long resourceId, String appCode, List<Long> roleIds) {
        List<ActionResVO> actions = new ArrayList<>();
        List<SysResourceAction> sysResourceActions = sysResourceDomain.qryResourceAction(appCode, resourceId, roleIds);
        if (!CollectionUtils.isEmpty(sysResourceActions)) {
            sysResourceActions.forEach(item -> {
                ActionResVO action = new ActionResVO();
                BeanUtils.copyProperties(item, action);
                actions.add(action);
            });
        }
        return actions;
    }

    private List<ActionResVO> getResourceActionList(Long resourceId, String appCode) {
        List<ActionResVO> actions = new ArrayList<>();
        List<SysResourceAction> sysResourceActions = sysResourceDomain.qryByResourceIdAndAppCode(resourceId, appCode);
        if (!CollectionUtils.isEmpty(sysResourceActions)) {
            sysResourceActions.forEach(item -> {
                ActionResVO action = new ActionResVO();
                action.setActionCode(item.getActionCode());
                action.setActionName(item.getActionName());
                actions.add(action);
            });
        }
        return actions;
    }

    @Override
    //课题专供-增删改
    public BaseResult<String> operateResourceForSub(@RequestBody ResourceInfoVo vo) {
        if (ObjectUtils.isEmpty(vo)) {
            return BaseResult.buildError("入参不能为空！");
        }
        if (ObjectUtils.isEmpty(vo.getResourceCode()) || ObjectUtils.isEmpty(vo.getResourceName())) {
            return BaseResult.buildError("资源编码和资源名称不能为空！");
        }
        if (ObjectUtils.isEmpty(vo.getOperateType())) {
            return BaseResult.buildError("操作类型不能为空！");
        }
        if (ObjectUtils.isEmpty(vo.getAppCode())) {
            return BaseResult.buildError("应用编码不能为空！");
        }
        SysResource sysResource = sysResourceDomain.qryResourceByResourceCodeAndAppCode(vo.getResourceCode(), vo.getAppCode());
        if (OperateEnum.ADD.getCode() == vo.getOperateType()) {
            if (!ObjectUtils.isEmpty(sysResource)) {
                return BaseResult.buildError("资源编码" + vo.getResourceCode() + "已存在！");
            }
            sysResource = new SysResource();
            BeanUtils.copyProperties(vo, sysResource);
            sysResource.setResourceType(1L);
            if (ObjectUtils.isEmpty(vo.getParentResourceId())) {
                sysResource.setParentId(sysResourceDomain.qryResourceRootId(vo.getAppCode()));
            } else {
                sysResource.setParentId(vo.getParentResourceId());
            }
            sysResource.setGmtCreated(LocalDateTime.now());
            sysResource.setCreator("superAdmin");
            sysResource.setMenuFlag(3);
            sysResource.setHasChild(Boolean.FALSE);
            sysResource.setIsLink(Boolean.FALSE);
            sysResourceDomain.insert(sysResource);
        } else if (OperateEnum.UPDATE.getCode() == vo.getOperateType()) {
            if (ObjectUtils.isEmpty(sysResource)) {
                return BaseResult.buildError("资源编码" + vo.getResourceCode() + "不存在！");
            }
            sysResource.setResourceName(vo.getResourceName());
            sysResource.setGmtModified(LocalDateTime.now());
            sysResource.setModifier("superAdmin");
            sysResourceDomain.updateById(sysResource);
        } else if (OperateEnum.DELETE.getCode() == vo.getOperateType()) {
            if (ObjectUtils.isEmpty(sysResource)) {
                return BaseResult.buildError("资源编码" + vo.getResourceCode() + "不存在！");
            }
            sysResource.setGmtModified(LocalDateTime.now());
            sysResource.setIsDeleted("Y");
            sysResourceDomain.updateById(sysResource);
        } else {
            return BaseResult.buildError("操作类型错误！");
        }
        if (!ObjectUtils.isEmpty(vo.getParentResourceId())) {
            SysResource parentResource = sysResourceDomain.getById(vo.getParentResourceId());
            if (!ObjectUtils.isEmpty(parentResource) && !parentResource.getHasChild()) {
                parentResource.setHasChild(true);
                parentResource.setGmtModified(LocalDateTime.now());
                sysResourceDomain.updateById(parentResource);
            }
        }
        return BaseResult.buildSuccess("操作成功!");
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public BaseResult<UserResourceResVO> qryResourceListByUserId(SelectUserResourceReqVO vo) {
        return BaseResult.buildSuccess(null);
    }

    @Override
    public BaseResult<RpcResourceResVO> qryResourceListByRoleId(SelectRoleResourceReqVO paramVO) {
        if (null == paramVO) {
            return BaseResult.buildError("参数对象不能为空");
        }
        if (null == paramVO.getAppCode() && CollectionUtils.isEmpty(paramVO.getRoleIdList())
                && StringUtils.isEmpty(paramVO.getResourcePath())) {
            return BaseResult.buildError("参数属性不能全部为空");
        }

        RpcResourceResVO rpcResourceResVO = null;
        //只查询非组件本身的菜单
        paramVO.setMenuFlag(1);
        // 1.查询菜单列表
        List<ResourceResVO> menuList = sysResourceDomain.qryResourceListByRoleId(paramVO);
        if (!ObjectUtils.isEmpty(menuList)) {
            rpcResourceResVO = new RpcResourceResVO();
            // 1.1过滤掉重复的资源
            menuList = menuList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(ResourceResVO::getResourceId))), ArrayList::new));
            rpcResourceResVO.setMenuList(menuList);
            // 1.2构造按钮列表查询条件
            List<Long> resourceIdList = menuList.stream().map(ResourceResVO::getResourceId).collect(Collectors.toList());
            SelectRoleResourceActionReqVO selectRoleResourceActionReqVO = new SelectRoleResourceActionReqVO();
            // 查询条件不设置roleIdList，查询出所有按钮，再根据连表查询出的roleId进行标记已授权的按钮
            selectRoleResourceActionReqVO.setAppCode(paramVO.getAppCode());
            selectRoleResourceActionReqVO.setResourceIdList(resourceIdList);
            // 2.查询资源下所有按钮列表
            List<RoleResourceActionResVO> roleResourceActionResVOS = sysResourceDomain.qryRoleResourceActionListByRoleId(selectRoleResourceActionReqVO);
            List<ResourceActionResVO> buttonList = null;
            // 2.1根据角色id标记已授权按钮,已授权的按钮roleIdList不为空，roleIdList存放有该按钮权限的角色id
            if (!ObjectUtils.isEmpty(roleResourceActionResVOS)) {
                Map<Long, ResourceActionResVO> buttonMap = new HashMap<>();
                List<Long> roleIdListReq = paramVO.getRoleIdList();
                roleResourceActionResVOS.forEach(
                        roleResourceActionResVO -> {
                            Long resourceActionId = roleResourceActionResVO.getResourceActionId();
                            ResourceActionResVO resourceActionResVO = buttonMap.get(resourceActionId);
                            if (ObjectUtils.isEmpty(resourceActionResVO)) {
                                resourceActionResVO = new ResourceActionResVO();
                                BeanUtils.copyProperties(roleResourceActionResVO, resourceActionResVO);
                            }
                            // 标记已授权的按钮
                            Long roleId = roleResourceActionResVO.getRoleId();
                            // 请求roleIdListReq包含该roleId则标记为已授权，放入roleIdList中
                            if (roleIdListReq.contains(roleId)) {
                                List<Long> roleIdList = resourceActionResVO.getRoleIdList();
                                if (ObjectUtils.isEmpty(roleIdList)) {
                                    roleIdList = new ArrayList<>();
                                }
                                // 过滤重复的roleId
                                if (!roleIdList.contains(roleId)) {
                                    roleIdList.add(roleId);
                                    resourceActionResVO.setRoleIdList(roleIdList);
                                }
                            }
                            buttonMap.put(resourceActionId, resourceActionResVO);
                        }
                );
                buttonList = new ArrayList<>(buttonMap.values());
            }
            rpcResourceResVO.setButtonList(buttonList);
        }
        return BaseResult.buildSuccess(rpcResourceResVO);
    }

    @Override
    public BaseResult<RpcResourceResVO> qryResourceListByAppOrPath(SelectAppResourceReqVO vo) {
        // 检查参数合法性
        if (null == vo || StringUtils.isEmpty(vo.getAppCode())) {
            throw new BaseException(BaseErrorCode.PARAM_IS_NULL.getCode(), BaseErrorCode.PARAM_IS_NULL.getMessage());
        }
        // 查询资源列表
        List<ResourceResVO> resourceResVOList = sysResourceDomain.qryResourceListByAppOrPath(vo);
        if (null == resourceResVOList) {
            resourceResVOList = new ArrayList<>();
        }
        // 查询Action列表
        List<ResourceActionResVO> resourceActionResVOList = sysResourceDomain.qryResourceActionListByAppOrPath(vo);
        if (null == resourceActionResVOList) {
            resourceActionResVOList = new ArrayList<>();
        }
        // 整体返回
        RpcResourceResVO rpcResourceResVO = new RpcResourceResVO();
        rpcResourceResVO.setMenuList(resourceResVOList);
        rpcResourceResVO.setButtonList(resourceActionResVOList);
        return BaseResult.buildSuccess(rpcResourceResVO);
    }

    //查询树状的菜单资源(菜单和按钮)列表
//    @Override
//    @Transactional(propagation = Propagation.REQUIRED, readOnly = true, rollbackFor = Exception.class)
//    public BaseResult<List<ResourceDetailInfoResVO>> qryAllResourceList(String tantentcode) {
//        List<Integer> resourceTypeList = SysResourceTypeEnum.getMenuTypeList();
//        SysResource sysResource = new SysResource();
//        sysResource.setResourceTypeList(resourceTypeList);
//        List<SysResource> sysResourceList = sysResourceDomain.listByPara(sysResource, null);
//        List<ResourceDetailInfoResVO> result = new ArrayList<>();
//        sysResourceList.forEach(s -> {
//            ResourceDetailInfoResVO resVO = new ResourceDetailInfoResVO();
//            BeanUtils.copyProperties(s, resVO);
//            result.add(resVO);
//        });
//        List<ResourceDetailInfoResVO> res = TreeUtils.generateTree(result, ResourceDetailInfoResVO::getId, ResourceDetailInfoResVO::getParentId, ResourceDetailInfoResVO::getChildList);
//        return BaseResult.buildSuccess(result);
//    }

}

